home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / progutil / stdwin.zoo / vt / vtansi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-18  |  7.3 KB  |  397 lines

  1. /* ANSI escape sequence interpreter */
  2. /* $Header: vtansi.c,v 1.6 88/06/20 22:38:12 guido Exp $ */
  3.  
  4. /* There is some ugly code here, since I assume that code looking
  5.    at the input a character at a time is very time-critical.
  6.    Action functions are called with the start of the text to process,
  7.    and return a pointer to where they left off.
  8.    When an action function hits the end of the string,
  9.    it returns NULL and sets the action pointer to the function to
  10.    call next (often itself), or to NULL for the default.
  11.    A non-NULL return implies that the default action function must
  12.    be called next and the action pointer is irrelevant.
  13.    Remember that the general form of most ANSI escape sequences is
  14.     ESC [ <n1> ; <n2> ; ... <c>
  15.    where <c> is the command code and <n1>, <n2> etc. are optional
  16.    numerical parameters.
  17. */
  18.  
  19. #include "vtimpl.h"
  20.  
  21. /* Function prototypes */
  22.  
  23. STATIC char *def_action ARGS((VT *vt, char *text, char *end));
  24. STATIC char *esc_action ARGS((VT *vt, char *text, char *end));
  25. STATIC char *ansi_params ARGS((VT *vt, char *text, char *end));
  26. STATIC char *ansi_execute ARGS((VT *vt, char *text));
  27. STATIC void vtsetoptions ARGS((VT *vt, bool flag));
  28. STATIC void vtsetattrlist ARGS((VT *vt));
  29.  
  30. /* Output a string, interpreting ANSI escapes */
  31.  
  32. void
  33. vtansiputs(vt, text, len)
  34.     VT *vt;
  35.     char *text;
  36.     int len;
  37. {
  38.     char *end;
  39.     
  40.     if (len < 0)
  41.         len= (int)strlen(text);
  42.     end= text + len;
  43.     
  44.     /* Pick up where the last call left us behind  */
  45.     
  46.     if (vt->action != NULL)
  47.         text= (*vt->action)(vt, text, end);
  48.     
  49.     /* Start in default state until text exhausted */
  50.     
  51.     while(text != NULL)
  52.         text= def_action(vt, text, end);
  53.     
  54.     /* Execute delayed scrolling */
  55.     
  56.     vtsync(vt);
  57. }
  58.  
  59. /* Default action function */
  60.  
  61. static char *
  62. def_action(vt, text, end)
  63.     VT *vt;
  64.     char *text, *end;
  65. {
  66. again:
  67.     for (;;) {
  68.         if (text >= end) {
  69.             vt->action= NULL;
  70.             return NULL;
  71.         }
  72.         if (PRINTABLE(*text))
  73.             break;
  74.         switch (*text++) {
  75.         
  76.         case ESC:    /* ESC */
  77.             return esc_action(vt, text, end);
  78.         
  79.         case BEL:    /* Bell */
  80.             wfleep();
  81.             break;
  82.         
  83.         case BS:    /* Backspace -- move 1 left */
  84.             /* Rely on vtsetcursor's clipping */
  85.             vtsetcursor(vt, vt->cur_row, vt->cur_col - 1);
  86.             /* Don't erase --
  87.                that's part of intelligent echoing */
  88.             break;
  89.         
  90.         case TAB:    /* Tab -- move to next tab stop */
  91.             /* Rely on vtsetcursor's clipping */
  92.             /* TO DO: use programmable tab stops! */
  93.             vtsetcursor(vt, vt->cur_row,
  94.                 (vt->cur_col & ~7) + 8);
  95.             /* Normalize cursor (may cause scroll!) */
  96.             vtputstring(vt, "", 0);
  97.             break;
  98.         
  99.         case LF:    /* Linefeed -- move down one line */
  100.             if (vt->nlcr)
  101.                 vtsetcursor(vt, vt->cur_row, 0);
  102.             vtlinefeed(vt, 1);
  103.             break;
  104.         
  105.         case FF:    /* Formfeed */
  106.             /* vtreset(vt); */
  107.             break;
  108.         
  109.         case CR:    /* Return -- to col 0 on same line */
  110.             vtsetcursor(vt, vt->cur_row, 0);
  111.             break;
  112.         
  113.         default:
  114.             FAIL();
  115.             break;
  116.         }
  117.     }
  118.     
  119.     /* We fall through the previous loop when we get a printable
  120.        character */
  121.     
  122.     {
  123.         char *p= text;
  124.         
  125.         while (PRINTABLE(*++p)) {
  126.             /* At least one character guaranteed! */
  127.             if (p >= end)
  128.                 break;
  129.         }
  130.         vtputstring(vt, text, (int)(p-text));
  131.         text= p;
  132.         goto again;
  133.     }
  134. }
  135.  
  136. /* Action function called after ESC seen */
  137.  
  138. static char *
  139. esc_action(vt, text, end)
  140.     VT *vt;
  141.     char *text, *end;
  142. {
  143.     if (text >= end) {
  144.         vt->action= esc_action;
  145.         return NULL;
  146.     }
  147.     switch (*text++) {
  148. /*
  149.     case '(':
  150.     case ')':
  151.     case '*':
  152.     case '+':
  153.         return cset_action(vt, text, end);
  154. */
  155.     case '=':
  156.         vt->keypadmode= TRUE;
  157.         break;
  158.     case '>':
  159.         vt->keypadmode= FALSE;
  160.         break;
  161.     case '7':
  162.         vtsavecursor(vt);
  163.         break;
  164.     case '8':
  165.         vtrestorecursor(vt);
  166.         break;
  167.     case 'D':
  168.         vtlinefeed(vt, 1);
  169.         break;
  170.     case 'E':
  171.         /* Next Line */
  172.         break;
  173.     case 'H':
  174.         /* Tab set */
  175.         break;
  176.     case 'M':
  177.         vtrevlinefeed(vt, 1);
  178.         break;
  179.     case '[':
  180.         vt->nextarg= vt->args;
  181.         *vt->nextarg= -1;
  182.         vt->modarg= FALSE;
  183.         return ansi_params(vt, text, end);
  184.     case 'c':
  185.         vtreset(vt);
  186.         break;
  187.     default:
  188.         FAIL();
  189.         break;
  190.     }
  191.     return text;
  192. }
  193.  
  194. /* Action function called after ESC-[ plus possible parameters seen */
  195.  
  196. static char *
  197. ansi_params(vt, text, end)
  198.     VT *vt;
  199.     char *text, *end;
  200. {
  201. again:
  202.     if (text >= end) {
  203.         vt->action= ansi_params;
  204.         return NULL;
  205.     }
  206.     if (isdigit(*text)) {
  207.         long a= *vt->nextarg;
  208.         if (a < 0)
  209.             a= 0;
  210.         do {
  211.             a= a*10 + (*text - '0');
  212.             CLIPMAX(a, 0x7fff); /* Avoid overflow */
  213.         } while (++text < end && isdigit(*text));
  214.         *vt->nextarg= a;
  215.         if (text >= end)
  216.             goto again;
  217.     }
  218.     switch (*text) {
  219.     
  220.     case ';':
  221.         ++text;
  222.         if (vt->nextarg < &vt->args[VTNARGS-1])
  223.             ++vt->nextarg;
  224.         *vt->nextarg= -1;
  225.         goto again;
  226.     
  227.     case '?':
  228.         ++text;
  229.         if (vt->nextarg == vt->args &&
  230.             *vt->nextarg < 0 && !vt->modarg) {
  231.             vt->modarg= TRUE;
  232.             goto again;
  233.         }
  234.         else {
  235.             FAIL();
  236.             return text;
  237.         }
  238.     
  239.     default:
  240.         return ansi_execute(vt, text);
  241.     
  242.     }
  243. }
  244.  
  245. /* Action function called at last char of ANSI sequence.
  246.    (This is only called when the char is actually seen,
  247.    so there is no need for an 'end' parameter). */
  248.  
  249. static char *
  250. ansi_execute(vt, text)
  251.     VT *vt;
  252.     char *text;
  253. {
  254.     int a1= vt->args[0];
  255.     int a2= (vt->nextarg > vt->args) ? vt->args[1] : -1;
  256.     
  257.     if (vt->modarg)
  258.         return ++text; /* No semantics for those functions yet */
  259.     
  260.     CLIPMIN(a1, 1);
  261.     CLIPMIN(a2, 1);
  262.     
  263.     switch (*text++) {
  264.     
  265.     case '@': vtinschars(vt, a1);        break;
  266.     
  267.     case 'A': vtarrow(vt, WC_UP, a1);    break;
  268.     
  269.     case 'B': vtarrow(vt, WC_DOWN, a1);    break;
  270.     
  271.     case 'C': vtarrow(vt, WC_RIGHT, a1);    break;
  272.     
  273.     case 'D': vtarrow(vt, WC_LEFT, a1);    break;
  274.     
  275.     case 'H':
  276.     case 'f': vtsetcursor(vt, vt->topterm + a1 - 1, a2-1);
  277.                         break;
  278.     
  279.     case 'J':
  280.         switch (vt->args[0]) {
  281.         case -1:
  282.         case 0:
  283.             vteosclear(vt, vt->topterm, 0);
  284.             break;
  285.         case 1:
  286.             /* clear above cursor */
  287.             break;
  288.         case 2:
  289.             vteosclear(vt, vt->cur_row, vt->cur_col);
  290.             break;
  291.         default:
  292.             FAIL();
  293.             break;
  294.         }
  295.         break;
  296.     
  297.     case 'K':
  298.         switch (vt->args[0]) {
  299.         case -1:
  300.         case 0:
  301.             vteolclear(vt, vt->cur_row, vt->cur_col);
  302.             break;
  303.         case 1:
  304.             /* Clear left of cursor */
  305.             break;
  306.         case 2:
  307.             vteolclear(vt, vt->cur_row, 0);
  308.             break;
  309.         default:
  310.             FAIL();
  311.             break;
  312.         }
  313.         break;
  314.     
  315.     case 'L': vtinslines(vt, a1);        break;
  316.     
  317.     case 'M': vtdellines(vt, a1);        break;
  318.     
  319.     case 'P': vtdelchars(vt, a1);        break;
  320.     
  321.     case 'S': vtlinefeed(vt, a1);        break;
  322.     
  323.     case 'T': vtrevlinefeed(vt, a1);    break;
  324.     
  325.     case 'c': vtsendid(vt);            break;
  326.     
  327.     case 'g': /* Tab clear */        break;
  328.         /* 0: current col; 3: all */
  329.     
  330.     case 'h': vtsetoptions(vt, TRUE);    break;
  331.     
  332.     case 'l': vtsetoptions(vt, FALSE);    break;
  333.     
  334.     case 'm': vtsetattrlist(vt);        break;
  335.     
  336.     case 'n': if (a1 == 6) vtsendpos(vt);    break;
  337.         /* 5: echo 'ESC [ 0 n' */
  338.     
  339.     case 'r': vtsetscroll(vt, vt->topterm + vt->args[0] - 1,
  340.                 vt->topterm + a2);
  341.                         break;
  342.     
  343.     case 'x': /* Send terminal params */    break;
  344.     
  345.     default: FAIL();            break;
  346.     
  347.     }
  348.     
  349.     return text;
  350. }
  351.  
  352. /* Set/reset numbered options given in args array */
  353.  
  354. static void
  355. vtsetoptions(vt, flag)
  356.     VT *vt;
  357.     bool flag; /* Set/reset */
  358. {
  359.     short *a;
  360.     for (a= vt->args; a <= vt->nextarg; ++a) {
  361.         switch (*a) {
  362.         case 4:
  363.             vtsetinsert(vt, flag);
  364.             break;
  365.         case -1:
  366.             /* Empty parameter, don't beep */
  367.             break;
  368.         default:
  369.             FAIL();
  370.             break;
  371.         }
  372.     }
  373. }
  374.  
  375. /* Set/reset output mode attributes given in args array */
  376.  
  377. static void
  378. vtsetattrlist(vt)
  379.     VT *vt;
  380. {
  381.     short *a;
  382.     for (a= vt->args; a <= vt->nextarg; ++a) {
  383.         switch (*a) {
  384.         case -1:
  385.             if (a == vt->args)
  386.                 vtresetattr(vt);
  387.             break;
  388.         case 0:
  389.             vtresetattr(vt);
  390.             break;
  391.         default:
  392.             vtsetattr(vt, *a);
  393.             break;
  394.         }
  395.     }
  396. }
  397.